package com.chenfan.common.extension.mybatisplus.enhanced;

import com.chenfan.common.extension.util.ApplicationShutdownHook;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 增强Bean工厂类
 *
 * @author wulg
 * @date 2021-09-07
 **/
class EnhancedBeanFactory {

    private static Map<EnhancedService, EnhancedBaseMapper> MAP = new ConcurrentHashMap<>(64);

    static {
        ApplicationShutdownHook.add(() -> MAP.clear());
    }

    /**
     * 注册
     * @param enhancedService
     * @param enhancedBaseMapper
     */
    public static synchronized void register(EnhancedService enhancedService, EnhancedBaseMapper enhancedBaseMapper) {
        if(contains(enhancedService)) {
            return;
        }
        if(enhancedBaseMapper == null ) {
            Class<? extends EnhancedBaseMapper> mapperClass = getBaseEnhancedMapper(enhancedService);
            throw new IllegalStateException(String.format("%s bean depends on %s bean",enhancedService.getClass().getSimpleName(),mapperClass.getSimpleName()));
        }
        MAP.putIfAbsent(enhancedService, enhancedBaseMapper);
    }

    /**
     * 是否含有
     * @param enhancedService
     * @return
     */
    public static boolean contains(EnhancedService enhancedService) {
        return MAP.containsKey(enhancedService);
    }

    /**
     * 注销
     * @param enhancedService
     */
    public static void unregister(EnhancedService enhancedService) {
        MAP.remove(enhancedService);
    }

    /**
     * 获取EnhancedService依赖的EnhancedBaseMapper
     * @param bean
     * @param <M>
     * @param <T>
     * @return
     */
    public static <M extends EnhancedBaseMapper, T> EnhancedBaseMapper<T> getMapper(EnhancedService<M, T> bean) {
        if (!MAP.containsKey(bean)) {
            Class<? extends EnhancedBaseMapper> mapperClass = getBaseEnhancedMapper(bean);
            throw new IllegalStateException(String.format("%s bean depends on %s bean",bean.getClass().getSimpleName(),mapperClass.getSimpleName()));
        }
        return MAP.get(bean);
    }

    /**
     * 获取继承EnhancedService类所依赖的EnhancedBaseMapper.class
     * @param bean
     * @return
     */
    private static Class<? extends EnhancedBaseMapper> getBaseEnhancedMapper(EnhancedService bean) {
        Class<? extends EnhancedService> serviceClass = bean.getClass();
        Type[] interfaceTypes = getEnhancedServiceClass(serviceClass).getGenericInterfaces();
        ParameterizedType parameterizedType = null;
        for (Type interfaceType : interfaceTypes) {
            if (!(interfaceType instanceof ParameterizedType)) {
                continue;
            }
            parameterizedType = (ParameterizedType) interfaceType;
        }
        Class<? extends EnhancedBaseMapper> mapperClass = (Class<? extends EnhancedBaseMapper>) parameterizedType.getActualTypeArguments()[0];
        return mapperClass;
    }

    /**
     * 获取继承的EnhancedService.class
     * @param serviceClass
     * @return
     */
    private static Class<?> getEnhancedServiceClass(Class<? extends EnhancedService> serviceClass) {
        for (Class<?> clazz : serviceClass.getInterfaces()) {
            if (EnhancedService.class.isAssignableFrom(clazz)) {
                return clazz;
            }
        }
        return null;
    }
}
